﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using FBEntities;
using FBEntities.FBConnections.User;
using FBEntities.FBObjects;
using FBEntities.FBObjects.User;
using Newtonsoft.Json.Linq;
using XDAFacebook;
using XFControls.Utils;
using XFControls.XFPanels;
using XFControls.XFPanels.XFPanelItems;
using XFItemControls.XFPanels.XFPanelItems;
using XFSenseUI.XFItems;
using XFSenseUI.XFItems.SenseControls;
using Microsoft.WindowsMobile.Samples.Location;
using System.IO;

namespace XFControls
{
    public static class XFItemControlUtils
    {
        #region Delegates

        public delegate void AddFriendsDel(XFPanelList panel, FBDataSource ds);

        #endregion

        public static FBDataSource Me { get; set; }

        public static void AddFriends(XFPanelList panel, FBDataSource ds)
        {

            if (ds.Me.Friends.data.Count == 0)
            {
                var empty = new XFItemSimpleText(Settings.LocalizationStrings.NoFriends);
                panel.Add(empty);
                panel.ScrollbarColor = Color.LightSlateGray;
                return;
            }

            var worker = new XFWorkerLoadFriendsStatus(ds.Me);
            var loading = new XFItemLoading(worker, false);
            panel.Add(loading);
            loading.DoWork();

            loading.WorkFinished += LoadingWorkFinished;

            List<FBProxyPerson> friends = ds.Me.Friends.data;
            friends.Sort(FriendCompare);
            char[] curLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            int cur = 0;
            panel.Add(curLetter[cur].ToString());

            foreach (FBProxyPerson friend in friends)
            {
                string fLast = friend.name.Split(' ').Last();

                if (!fLast.StartsWith(curLetter[cur].ToString()))
                {
                    int tempCur = Array.IndexOf(curLetter, fLast[0]);
                    if (tempCur > 0)
                    {
                        cur = tempCur;
                        panel.Add(curLetter[cur].ToString());
                    }
                }

                var f = new XFItemFriend { Name = friend.name, Friend = friend, status = friend.status };
                panel.Add(f);
            }

            addSearch(panel);
        }

        public static WebDownloaderWrapper GetFQL(string fql)
        {
            var args = new Dictionary<string, string> { { "query", fql }, { "format", "json" }, { "access_token", FBParseUtilities.authKeySplit } };
            var vars = RequestUtil.EncodeDictionary(args, true);
            var url = "https://api.facebook.com/method/fql.query" + vars;
            var wrapper = new WebDownloaderWrapper(url);
            return wrapper;
        }

        static void LoadingWorkFinished(object sender, WorkerEventArgs e)
        {
            var worker = (XFWorkerLoadFriendsStatus)e.Worker;
            var loading = (XFItemLoading)sender;
            var parent = (XFPanelList)loading.Parent;

            if (parent == null || parent.IsDisposed) return;

            var friends = worker.Person.Friends.data;
            foreach (IXFItem item in parent)
            {
                if (!(item is XFItemFriend)) continue;

                var friend = (XFItemFriend)item;
                var proxyPerson = friends.FirstOrDefault(f => f.id == friend.Friend.id);

                if (proxyPerson == null) continue;
                friend.status = proxyPerson.status;
                friend.Reset();
            }
        }

        private static void addSearch(XFPanelList panel)
        {
            var search = new SenseItemTextBox
                         {
                             Description = Settings.LocalizationStrings.SearchFriends
                         };

            search.TextChanged += (o, e) =>
                                  {
                                      XFItemBase letter = null;
                                      bool show = false;
                                      foreach (object itm in panel)
                                      {
                                          if (itm is XFItemSimpleText)
                                          {
                                              if (letter != null)
                                              {
                                                  letter.Visible = show;
                                              }
                                              show = false;
                                              letter = itm as XFItemSimpleText;
                                          }
                                          if (itm is XFItemFriend)
                                          {
                                              var fItem = itm as XFItemFriend;
                                              if (!fItem.Name.Contains(e.Text,
                                                                       StringComparison.CurrentCultureIgnoreCase))
                                                  fItem.Visible = false;
                                              else
                                              {
                                                  fItem.Visible = true;
                                                  show = true;
                                              }
                                          }
                                          if (itm is SenseItem)
                                          {
                                              var fItem = itm as SenseItem;
                                              if (!fItem.MainText.Contains(e.Text,
                                                                       StringComparison.CurrentCultureIgnoreCase))
                                                  fItem.Visible = false;
                                              else
                                              {
                                                  fItem.Visible = true;
                                                  show = true;
                                              }
                                          }
                                      }
                                      panel.Resize();
                                      panel.Invalidate();
                                  };

            panel.Add(search, 1);
        }

        private static int FriendCompare(FBProxyPerson f1, FBProxyPerson f2)
        {
            string f1Last = f1.name.Split(' ').Last();
            string f2Last = f2.name.Split(' ').Last();

            return f1Last.CompareTo(f2Last);
        }

        public static XFPanelList SetupProfile(FBPerson pers)
        {
            var panel = new XFPanelList { ScrollbarColor = Color.LightSlateGray, PanelName = pers.name };

            FBPerson cachedPerson = pers;

            var headCache = new XFItemProfileHead { User = cachedPerson };

            //var tabsCache = new XFItemProfileTabs { User = cachedPerson };
            var tabsCache = new XFItemThreeTabs(XFItemTabs.Two)
                                {
                                    TabOne = Settings.LocalizationStrings.Wall,
                                    TabTwo = Settings.LocalizationStrings.Info,
                                    TabThree = Settings.LocalizationStrings.Photos,
                                    Tag = cachedPerson
                                };

            tabsCache.OneClick += Profile_OneClick;
            tabsCache.TwoClick += Profile_TwoClick;
            tabsCache.ThreeClick += Profile_ThreeClick;

            if (File.Exists(Settings.SkinDir + "\\" + Settings.Skin + "\\ProfileTabs.png"))
                tabsCache.Style.BackgroundImageString = "ProfileTabs";
            var itmCache = GetProfileInfoLoading(cachedPerson, panel);

            //var poke = new XFItemPokeButton(pers)
            //               {
            //                   MainText = "Poke",
            //                   SecondaryText = "Disabled",
            //                   Icon = "poke"
            //               };

            //poke.Style.BackgroundColor = Color.White;

            panel.Add(headCache);
            panel.Add(tabsCache);
            //if (pers.id != Me.Me.id)
            //    panel.Add(poke);

            panel.Add(itmCache);
            return panel;
        }

        static void Profile_ThreeClick(object sender, XFPanelListEventArgs e)
        {
            var user = (FBPerson)((XFItemThreeTabs)sender).Tag;
            var par = e.List;

            var albumWorker = new XFWorkerLoadAlbum(user);
            var newAlbum = new SenseItem
            {
                MainText = Settings.LocalizationStrings.createNewAlbum,
                ClickResults = XFItemClickResult.SlideLeft
            };
            newAlbum.Style.BackgroundColor = Color.White;

            newAlbum.Click += (o, ex) =>
            {
                XFPanelList panel = SetupNewAblum();
                panel.Add(new XFItemBackHeader());

                par.SetRightPanel(panel);
            };

            var loading = new XFItemLoading(albumWorker);
            loading.WorkFinished += (o, ex) =>
            {
                FBPerson usr = ((XFWorkerLoadAlbum)ex.Worker).ParsedPerson;

                if (!par.IsDisposed)
                    par.Invoke(new Action(() =>
                    {
                        if (par.HasItem(loading))
                        {
                            par.ClearItemsAfterWaiting(loading);
                            if (usr.Albums == null || usr.Albums.data == null || usr.Albums.data.Count == 0)
                                par.Add(Settings.LocalizationStrings.noAlbums);
                            else
                                foreach (FBAlbum albm in usr.Albums.data)
                                    par.Add(new XFItemAlbum(albm));
                        }
                    }));
            };

            if (user.id == Me.Me.id)
                par.Add(newAlbum);
            par.Add(loading);
        }

        static void Profile_TwoClick(object sender, XFPanelListEventArgs e)
        {
            var user = (FBPerson)((XFItemThreeTabs)sender).Tag;
            var par = e.List;

            var loading = GetProfileInfoLoading(user, par);

            par.Add(loading);
        }

        static void Profile_OneClick(object sender, XFPanelListEventArgs e)
        {
            var user = (FBPerson)((XFItemThreeTabs)sender).Tag;
            var par = e.List;
            var wall = new XFWorkerLoadWall(user);


            var load = new XFItemExpander
            {
                PreThresholdText = Settings.LocalizationStrings.PreThreshold,
                PostThresholdText = Settings.LocalizationStrings.PostThreshold,
                Max = Settings.ExpanderMax,
                Threshold = Settings.ExpanderHeight
            };

            load.ReleasePostThreshold += (o, ex) =>
            {
                AsyncWebDownloader.ClearAsync();
                var loader = (XFItemExpander)o;
                var loaderPar = loader.Parent as XFPanelList;

                loader.Enabled = false;
                if (loaderPar == null) return;

                var worker = new XFWorkerLoadWall(user);
                var newLoading = new XFItemLoading(worker);

                newLoading.WorkFinished += ProfileWallLoadFinish;

                loaderPar.Add(newLoading, loaderPar[loader] + 1);

            };
            par.AddExpander(load);


            var postButton = new SenseItem
            {
                MainText = Settings.LocalizationStrings.writeSomething,
                ClickResults = XFItemClickResult.SlideLeft
            };
            postButton.Style.BackgroundColor = Color.White;

            postButton.Click += (clickSender, clickArgs) =>
            {
                var input = new XFPanelTextInput();

                input.Submitted += (o, ex) =>
                {
                    Cursor.Current = Cursors.WaitCursor;
                    Application.DoEvents();

                    var fbPost = new FBPost();
                    fbPost.message = ex.Text;
                    fbPost.to = new FBTo();
                    fbPost.to.data.Add(new FBProxyPerson { id = user.id });
                    FBPost result = FBPost.PostOnWall(fbPost);
                    par.Add(new XFItemPost(result),
                            par[postButton] + 1);

                    Cursor.Current = Cursors.Default;
                };

                par.SetRightPanel(input);
            };

            par.Add(postButton);

            var loading = new XFItemLoading(wall);

            loading.WorkFinished += ProfileWallLoadFinish;

            par.Add(loading);
        }

        public static XFPanelList SetupGroup(FBGroup pers)
        {
            var panel = new XFPanelList { ScrollbarColor = Color.LightSlateGray, PanelName = pers.name };
            var back = new XFItemBackHeader();

            var headCache = new XFItemGroupHead { Group = pers };

            var tabsCache = new XFItemThreeTabs(XFItemTabs.Two)
            {
                TabOne = Settings.LocalizationStrings.Wall,
                TabTwo = Settings.LocalizationStrings.Info,
                TabThree = Settings.LocalizationStrings.Members,
                Tag = pers
            };

            tabsCache.OneClick += Group_OneClick;
            tabsCache.TwoClick += Group_TwoClick;
            tabsCache.ThreeClick += Group_ThreeClick;

            if (File.Exists(Settings.SkinDir + "\\" + Settings.Skin + "\\ProfileTabs.png"))
                tabsCache.Style.BackgroundImageString = "ProfileTabs";
            var itmCache = GetGroupInfoLoading(pers, panel);

            panel.AddHeaderItem(back);
            panel.Add(headCache);
            panel.Add(tabsCache);
            panel.Add(itmCache);
            return panel;
        }

        static void Group_ThreeClick(object sender, XFPanelListEventArgs e)
        {
            var group = (FBGroup)((XFItemThreeTabs)sender).Tag;
            var par = e.List;

            var albumWorker = new XFWorkerLoadMembers(group);

            var loading = new XFItemLoading(albumWorker);
            loading.WorkFinished += (o, ex) =>
            {
                FBGroup usr = ((XFWorkerLoadMembers)ex.Worker).ParsedGroup;

                if (!par.IsDisposed)
                    par.Invoke(new Action(() =>
                    {
                        if (!par.HasItem(loading)) return;

                        par.ClearItemsAfterWaiting(loading);
                        if (usr.Members == null || usr.Members.data == null || usr.Members.data.Count == 0)
                            par.Add(Settings.LocalizationStrings.noAlbums);
                        else
                            foreach (var member in usr.Members.data)
                                par.Add(new XFItemFriend { Name = member.name, Friend = member });
                    }));
            };

            par.Add(loading);
        }

        static void Group_TwoClick(object sender, XFPanelListEventArgs e)
        {
            var group = (FBGroup)((XFItemThreeTabs)sender).Tag;
            var par = e.List;

            var loading = GetGroupInfoLoading(group, par);

            par.Add(loading);
        }

        static void Group_OneClick(object sender, XFPanelListEventArgs e)
        {
            var group = (FBGroup)((XFItemThreeTabs)sender).Tag;
            var par = e.List;
            var wall = new XFWorkerLoadGroupWall(group);


            var load = new XFItemExpander
            {
                PreThresholdText = Settings.LocalizationStrings.PreThreshold,
                PostThresholdText = Settings.LocalizationStrings.PostThreshold,
                Max = Settings.ExpanderMax,
                Threshold = Settings.ExpanderHeight
            };

            load.ReleasePostThreshold += (o, ex) =>
            {
                AsyncWebDownloader.ClearAsync();
                var loader = (XFItemExpander)o;
                var loaderPar = loader.Parent as XFPanelList;

                loader.Enabled = false;
                if (loaderPar == null) return;

                var worker = new XFWorkerLoadGroupWall(group);
                var newLoading = new XFItemLoading(worker);

                newLoading.WorkFinished += ProfileWallLoadFinish;

                loaderPar.Add(newLoading, loaderPar[loader] + 1);

            };
            par.AddExpander(load);


            var postButton = new SenseItem
            {
                MainText = Settings.LocalizationStrings.writeSomething,
                ClickResults = XFItemClickResult.SlideLeft
            };
            postButton.Style.BackgroundColor = Color.White;

            postButton.Click += (clickSender, clickArgs) =>
            {
                var input = new XFPanelTextInput();

                input.Submitted += (o, ex) =>
                {
                    Cursor.Current = Cursors.WaitCursor;
                    Application.DoEvents();

                    var fbPost = new FBPost();
                    fbPost.message = ex.Text;
                    fbPost.to = new FBTo();
                    fbPost.to.data.Add(new FBProxyPerson { id = group.id });
                    FBPost result = FBPost.PostOnWall(fbPost);
                    par.Add(new XFItemPost(result),
                            par[postButton] + 1);

                    Cursor.Current = Cursors.Default;
                };

                par.SetRightPanel(input);
            };

            par.Add(postButton);

            var loading = new XFItemLoading(wall);

            loading.WorkFinished += GroupWallLoadFinish;

            par.Add(loading);
        }

        private static void GroupWallLoadFinish(object sender, WorkerEventArgs args)
        {
            var group = ((XFWorkerLoadGroupWall)args.Worker).ParsedGroup;
            var loading = (XFItemLoading)sender;
            var par = (XFPanelList)loading.Parent;

            if (!par.IsDisposed)
                par.Invoke(new Action(() =>
                {
                    if (!par.HasItem(loading)) return;

                    par.ClearItemsAfterWaiting(loading);
                    if (group.Feed == null || group.Feed.data == null || group.Feed.data.Count == 0)
                    {
                        par.Add(Settings.LocalizationStrings.noPosts);
                        return;
                    }

                    foreach (var f in group.Feed.data)
                    {
                        var post = new XFItemPost(f);
                        par.Add(post);
                    }

                    var next = new SenseItem
                    {
                        Tag = group.Feed.paging.next,
                        MainText = Settings.LocalizationStrings.olderPosts
                    };

                    next.Click += NextClick;
                    next.Style.BackgroundColor = Color.White;
                    par.Add(next);

                }));
        }

        private static void ProfileWallLoadFinish(object sender, WorkerEventArgs args)
        {
            var usr = ((XFWorkerLoadWall)args.Worker).ParsedPerson;
            var loading = (XFItemLoading)sender;
            var par = (XFPanelList)loading.Parent;

            if (!par.IsDisposed)
                par.Invoke(new Action(() =>
                {
                    if (!par.HasItem(loading)) return;

                    par.ClearItemsAfterWaiting(loading);
                    if (usr.Feed == null || usr.Feed.data == null || usr.Feed.data.Count == 0)
                    {
                        par.Add(Settings.LocalizationStrings.noPosts);
                        return;
                    }

                    foreach (var f in usr.Feed.data)
                    {
                        var post = new XFItemPost(f);
                        par.Add(post);
                    }

                    var next = new SenseItem
                    {
                        Tag = usr.Feed.paging.next,
                        MainText = Settings.LocalizationStrings.olderPosts
                    };

                    next.Click += NextClick;
                    next.Style.BackgroundColor = Color.White;
                    par.Add(next);

                }));
        }

        private static void NextClick(object sender, EventArgs e)
        {
            var button = (SenseItem)sender;
            var parent = (XFPanelList)button.Parent;

            parent.ClearItem(button);

            var worker = new XFWorkerLoadWall(button.Tag.ToString());
            var loading = new XFItemLoading(worker);

            loading.WorkFinished += NextClickLoadingWorkFinished;
            button.Dispose();
            parent.Add(loading);
        }

        private static void NextClickLoadingWorkFinished(object sender, WorkerEventArgs e)
        {
            FBFeed feed = null;
            var loading = (XFItemLoading)sender;

            if (e.Worker is XFWorkerLoadWall)
                feed = ((XFWorkerLoadWall)e.Worker).Feed;

            var par = loading.Parent as XFPanelList;

            if (par != null && !par.IsDisposed)
                par.Invoke(new Action(() =>
                {
                    par.ClearItemsAfterWaiting(loading);

                    if (feed == null || feed.data == null) return;
                    foreach (FBPost p in feed.data)
                    {
                        var post = new XFItemPost(p);
                        par.Add(post);
                        par.RenderItemBuffer(post, false);
                    }

                    if (feed.paging == null) return;
                    var next = new SenseItem
                    {
                        Tag = feed.paging.next,
                        MainText = Settings.LocalizationStrings.olderPosts
                    };

                    next.Click += NextClick;
                    next.Style.BackgroundColor = Color.White;
                    par.Add(next);
                }));
        }

        private static XFItemLoading GetProfileInfoLoading(FBPerson user, XFPanelList par)
        {
            var worker = new XFWorkerLoadUserData(user);
            var loading = new XFItemLoading(worker) { WaitTillFinishSlide = true };
            loading.WorkFinished += (o, ex) =>
            {
                var wkr = (XFWorkerLoadUserData)ex.Worker;
                var itm = new XFItemProfileInfo { User = wkr.Person };

                if (par.IsDisposed) return;

                par.Invoke(new Action(() =>
                {
                    par.ClearItemsAfterWaiting(loading);
                    par.Add(itm);
                }));
            };

            return loading;
        }

        private static XFItemLoading GetGroupInfoLoading(FBGroup group, XFPanelList par)
        {
            var worker = new XFWorkerLoadGroup(group);
            var loading = new XFItemLoading(worker) { WaitTillFinishSlide = true };
            loading.WorkFinished += (o, ex) =>
            {
                var wkr = (XFWorkerLoadGroup)ex.Worker;
                var itm = new XFItemGroupInfo { Group = wkr.Group };

                if (par.IsDisposed) return;

                par.Invoke(new Action(() =>
                {
                    par.ClearItemsAfterWaiting(loading);
                    par.Add(itm);
                }));
            };

            return loading;
        }

        public static XFPanelList SetupPlaces()
        {
            var panel = new XFPanelList
                        {
                            ScrollbarColor = Color.LightSlateGray,
                            PanelName = Settings.LocalizationStrings.Places
                        };

            var tabs = new XFItemThreeTabs
                       {
                           TabOne = Settings.LocalizationStrings.Mine,
                           TabTwo = Settings.LocalizationStrings.Friends,
                           TabThree = Settings.LocalizationStrings.Checkin
                       };

            tabs.OneClick += Placestabs_OneClick;
            tabs.TwoClick += Placestabs_TwoClick;
            tabs.ThreeClick += Placestabs_ThreeClick;

            panel.Add(tabs);

            Placestabs_OneClick(null, new XFPanelListEventArgs(panel));

            return panel;
        }

        static void Placestabs_OneClick(object sender, XFPanelListEventArgs e)
        {
            var panel = e.List;

            panel.ClearItems(1);

            var worker = new XFWorkerLoadCheckins();
            var loading = new XFItemLoading(worker);

            loading.WorkFinished += (o, ex) =>
            {
                if (!panel.IsDisposed)
                    panel.Invoke(new Action(() =>
                        {
                            if (!panel.HasItem(loading)) return;
                            panel.ClearItemsAfterWaiting(loading);
                            foreach (var check in Me.Me.Checkins.data)
                            {
                                panel.Add(new XFItemPost(check.ToPost()));
                            }

                            if (Me.Me.Checkins.data.Count == 0)
                                panel.Add(Settings.LocalizationStrings.none);
                        }));
            };

            panel.Add(loading);
        }

        static void Placestabs_TwoClick(object sender, XFPanelListEventArgs e)
        {
            var panel = e.List;

            panel.ClearItems(1);

            var worker = new XFWorkerGeneric();
            var loading = new XFItemLoading(worker);

            EventHandler workEvent = (o, ex) =>
            {
                var me = Me.Me;

                me.FriendsCheckins = null;

                if (me.FriendsCheckins != null && !me.FriendsCheckins.Parsed) { }
            };

            worker.Work += workEvent;

            loading.WorkFinished += (o, ex) =>
            {
                worker.Work -= workEvent;
                if (!panel.IsDisposed)
                    panel.Invoke(new Action(() =>
                    {
                        if (!panel.HasItem(loading)) return;
                        panel.ClearItemsAfterWaiting(loading);
                        foreach (var check in Me.Me.FriendsCheckins.data)
                        {
                            panel.Add(new XFItemPost(check.ToPost()));
                        }

                        if (Me.Me.FriendsCheckins.data.Count == 0)
                            panel.Add(Settings.LocalizationStrings.none);
                    }));
            };

            panel.Add(loading);
        }

        static void Placestabs_ThreeClick(object sender, XFPanelListEventArgs e)
        {
            var panel = e.List;

            panel.ClearItems(1);

            var search = new SenseItemTextBox
                         {
                             Description = Settings.LocalizationStrings.LocalSearch
                         };

            var text = new XFItemSimpleText(Settings.LocalizationStrings.GettingGPS);
            var worker = new XFWorkerGPS(text);
            var loading = new XFItemLoading(worker);
            text.Style.Padding = 20;

            loading.WorkFinished += (o, ex) =>
            {
                if (!panel.IsDisposed)
                    panel.Invoke(new Action(() =>
                    {
                        if (!panel.HasItem(loading)) return;

                        var wrkr = (XFWorkerGPS)ex.Worker;
                        panel.ClearItemsAfterWaiting(loading);
                        if (wrkr.Places != null)
                            foreach (var place in wrkr.Places.data)
                            {
                                panel.Add(new XFItemPlace(place));
                            }

                        if (Me.Me.FriendsCheckins.data.Count == 0)
                            panel.Add(Settings.LocalizationStrings.none);
                    }));
            };


            panel.Add(search);
            panel.Add(loading);
            panel.Add(text);
        }

        public static XFPanelList SetupUserAlbums(FBPerson User)
        {
            var ret = new XFPanelList();
            var albumWorker = new XFWorkerLoadAlbum(User);
            var newAlbum = new SenseItem
                               {
                                   MainText = Settings.LocalizationStrings.createNewAlbum,
                                   ClickResults = XFItemClickResult.SlideLeft
                               };
            newAlbum.Click += (o, e) =>
                                  {
                                      XFPanelList panel = SetupNewAblum();
                                      panel.Add(new XFItemBackHeader());

                                      ret.SetRightPanel(panel);
                                  };

            var loading = new XFItemLoading(albumWorker);
            loading.WorkFinished += (o, e) =>
                                        {
                                            FBPerson usr = ((XFWorkerLoadAlbum)e.Worker).ParsedPerson;

                                            if (ret.IsDisposed) return;

                                            ret.Invoke(new Action(() =>
                                                      {
                                                          if (!ret.HasItem(loading)) return;

                                                          ret.ClearItemsAfterWaiting(loading);
                                                          if (usr.Albums == null ||
                                                              usr.Albums.data == null ||
                                                              usr.Albums.data.Count == 0)
                                                              ret.Add(Settings.LocalizationStrings.noAlbums);
                                                          else
                                                          {
                                                              ret.Add(new XFItemAlbum(new FBAlbum
                                                                                          {
                                                                                              id="me",
                                                                                              name="Me",
                                                                                              picture = Me.Me.Picture.url + "&type=large"
                                                                                          }));
                                                              foreach (var albm in usr.Albums.data)
                                                                  ret.Add(new XFItemAlbum(albm));
                                                          }
                                                      }));
                                        };

            if (User.id == Me.Me.id)
                ret.Add(newAlbum);
            ret.Add(loading);
            return ret;
        }

        public static XFPanelList SetupNewAblum()
        {
            var ret = new XFPanelList();
            WebDownloaderWrapper wrapper = null;
            var name = new SenseItemTextBox
                           {
                               Description = Settings.LocalizationStrings.Name
                           };

            var description = new SenseItemTextBox
                                  {
                                      Description = Settings.LocalizationStrings.Description,
                                      MultiLine = true
                                  };

            description.SetHeight(150);

            var buttons = new XFItemTwoButtons();

            buttons.Disposed += (o, e) =>
                                {
                                    if (wrapper != null)
                                        wrapper.Dispose();
                                };

            SenseControlButton rb = buttons.RightButton;
            SenseControlButton lb = buttons.LeftButton;

            rb.ButtonText = Settings.LocalizationStrings.Submit;
            lb.ButtonText = Settings.LocalizationStrings.Cancel;

            lb.Clicked += (o, e) => ret.EnableSlide();

            rb.Clicked += (o, e) =>
                              {
                                  if (!string.IsNullOrEmpty(name.Text))
                                  {
                                      var album = new FBAlbum
                                                      {
                                                          name = name.Text,
                                                          description = description.Text
                                                      };


                                      wrapper = album.Create();

                                      wrapper.GetResults += (wo, we) =>
                                                            {
                                                                if (!FBParseUtilities.HasError(we.Text))
                                                                    ret.EnableSlide();
                                                                else
                                                                    MessageBox.Show(Settings.LocalizationStrings.ErrorCreatingAlbum);
                                                            };

                                      wrapper.BeginDownload();
                                  }
                                  else
                                      MessageBox.Show(Settings.LocalizationStrings.GiveAlbumName);
                              };

            rb.Style.Padding = 25;
            lb.Style.Padding = 25;

            ret.Add(name);
            ret.Add(description);
            ret.Add(buttons);

            return ret;
        }

        public static XFPanelList SetupNotes()
        {
            var ret = new XFPanelList();

            var subject = new SenseItemTextBox
                              {
                                  Description = Settings.LocalizationStrings.Subject
                              };

            var Message = new SenseItemTextBox
                              {
                                  Description = Settings.LocalizationStrings.Message,
                                  MultiLine = true
                              };

            Message.SetHeight(150);

            var buttons = new XFItemTwoButtons();

            SenseControlButton rb = buttons.RightButton;
            SenseControlButton lb = buttons.LeftButton;

            rb.ButtonText = Settings.LocalizationStrings.Submit;
            lb.ButtonText = Settings.LocalizationStrings.Cancel;

            lb.Clicked += (o, e) => ret.EnableSlide();

            rb.Clicked += delegate
                          {
                              if (Validate(subject, Message))
                              {
                                  var note = new FBNote
                                             {
                                                 subject = subject.Text,
                                                 message = Message.Text
                                             };

                                  Cursor.Current = Cursors.WaitCursor;
                                  Application.DoEvents();

                                  var wrapper = note.Create();
                                  wrapper.GetResults += delegate
                                                        {
                                                            Cursor.Current = Cursors.Default;
                                                            Application.DoEvents();

                                                            ret.EnableSlide();
                                                        };
                                  wrapper.BeginPost();
                              }
                              else
                                  MessageBox.Show(Settings.LocalizationStrings.CompleteInfoNotes);
                          };

            rb.Style.Padding = 25;
            lb.Style.Padding = 25;

            ret.Add(subject);
            ret.Add(Message);
            ret.Add(buttons);

            return ret;
        }

        private static bool Validate(SenseItemTextBox subject, SenseItemTextBox Message)
        {
            return !(string.IsNullOrEmpty(subject.Text) || string.IsNullOrEmpty(Message.Text));
        }

        public static void SetupFriendSelector(XFPanelList toRight)
        {
            SetupFriendSelector(toRight, false);
        }

        public static void SetupFriendSelector(XFPanelList toRight, bool single)
        {
            if (!Me.Me.Friends.Parsed)
            {
                var worker = new XFWorkerLoadFriends(Me.Me);
                var loading = new XFItemLoading(worker);
                loading.WorkFinished += (o, e) => SetupFriendSelector(toRight);
                toRight.Add(loading);

                return;
            }
            SetupFriends(toRight, single);
        }

        private static void SetupFriends(XFPanelList toRight, bool single)
        {
            if (toRight.InvokeRequired)
            {
                if (!toRight.IsDisposed)
                    toRight.InvokeEx(() => SetupFriends(toRight, single));
                return;
            }

            toRight.ClearItems();
            var friends = Me.Me.Friends.data;

            friends.Sort(FriendCompare);

            var friendsPanel = new XFPanelList();

            toRight.ShowScrollbar(true);
            friendsPanel.ShowScrollbar(true);

            addSearch(single ? toRight : friendsPanel);

            foreach (var friend in friends)
            {
                var friendItem = new SenseItem
                                     {
                                         MainText = friend.name,
                                         Tag = friend
                                     };

                if (single)
                    friendItem.Click += friendItemSingleClick;
                else
                    friendItem.Click += friendItemMultiClick;

                if (single)
                    toRight.Add(friendItem);
                else
                    friendsPanel.Add(friendItem);
            }

            var add = new SenseItemMoreItems
                          {
                              MainText = Settings.LocalizationStrings.AddFriend,
                              SecondaryText = Settings.LocalizationStrings.ClickFriendToRemove,
                              MultiLine = true,
                              RightPanel = friendsPanel
                          };

            if (!single)
                toRight.Add(add);
        }

        static void friendItemSingleClick(object sender, EventArgs e)
        {
            var item = ((SenseItem)sender);
            item.State = XFItemState.Selected;
            item.Parent.EnableSlide();
        }

        static void friendItemMultiClick(object sender, EventArgs e)
        {
            var item = ((SenseItem)sender);
            var toRight = item.Parent.LeftPanel as XFPanelList;

            if (toRight == null) return;

            if (item.Style.BackgroundColor != Color.LavenderBlush)
            {
                var friendItemTo = new SenseItem
                {
                    MainText = ((FBProxyPerson)item.Tag).name,
                    Tag = item.Tag
                };
                friendItemTo.Click += (o, ex) =>
                {
                    item.Style.BackgroundColor =
                        Color.Empty;

                    item.Invalidate();

                    toRight.ClearItem(friendItemTo);
                };

                toRight.Add(friendItemTo);

                item.Style.BackgroundColor = Color.LavenderBlush;
            }
            else
            {
                foreach (IXFItem i in toRight)
                {
                    if (i is SenseItem && ((SenseItem)i).MainText == ((FBProxyPerson)item.Tag).name)
                        toRight.ClearItem(i);
                }

                item.Style.BackgroundColor = Color.White;
            }
        }

        internal static void AddMailItems(XFPanelList panel, FBDataSource dsInner)
        {
            if (panel.InvokeRequired)
            {
                if (!panel.IsDisposed)
                    panel.Invoke(new Action(() => { AddMailItems(panel, dsInner); }));
                return;
            }

            panel.ClearItems(1);

            foreach (FBMail item in dsInner.Me.Inbox.data)
            {
                panel.Add(new XFItemPost(item.ToPost()));
            }
        }

        internal static void AddNotes(XFPanelList panel, FBDataSource dsInner)
        {
            if (panel.InvokeRequired)
            {
                if (!panel.IsDisposed)
                    panel.Invoke(new Action(() => AddNotes(panel, dsInner)));
                return;
            }

            panel.ClearItems(1);

            foreach (FBNote item in dsInner.Me.Notes.data)
            {
                panel.Add(new XFItemPost(item.ToPost()));
            }
        }

        public static string ToFacebookTime(this DateTime time)
        {
            DateTime startTime = DateTime.UtcNow;
            TimeSpan span = startTime.Subtract(time);

            string display = "";
            if (span.Days > 0)
            {
                display = span.Days == 1
                              ? span.Days + " " + Settings.LocalizationStrings.dayAgo
                              : span.Days + " " + Settings.LocalizationStrings.daysAgo;
            }
            else if (span.Hours > 0)
            {
                display = span.Hours == 1
                              ? span.Hours + " " + Settings.LocalizationStrings.hourAgo
                              : span.Hours + " " + Settings.LocalizationStrings.hoursAgo;
            }
            else if (span.Minutes > 0)
            {
                display = span.Minutes == 1
                              ? span.Minutes + " " + Settings.LocalizationStrings.minAgo
                              : span.Minutes + " " + Settings.LocalizationStrings.minsAgo;
            }
            else if (span.Seconds > 0)
            {
                display = span.Seconds == 1
                              ? span.Seconds + " " + Settings.LocalizationStrings.secAgo
                              : span.Seconds + " " + Settings.LocalizationStrings.secsAgo;
            }
            else
            {
                display = Settings.LocalizationStrings.momentsAgo;
            }

            return display;
        }

        public static XFPanelList SetupCheckin(FBPlace place)
        {
            var panel = new XFPanelList
            {
                ScrollbarColor = Color.LightSlateGray
            };
            WebDownloaderWrapper wrapper;

            var placeItem = new XFItemPlace(place)
                            {
                                ItemType = XFItemType.Display
                            };
            panel.Add(placeItem);

            var message = new SenseItemTextBox
                          {
                              Description = Settings.LocalizationStrings.Message
                          };

            panel.Add(message);

            var friends = new SenseItemMoreItems
                                         {
                                             MainText = Settings.LocalizationStrings.TaggedFriends,
                                             MultiLine = true
                                         };

            friends.Draw += (o, e) =>
                            {
                                friends.ResetHeight();
                                string tagged = "";
                                foreach (SenseItem itm in ((XFPanelList)friends.RightPanel).OfType<SenseItem>())
                                {
                                    if (string.IsNullOrEmpty(tagged))
                                        tagged = (itm).MainText;
                                    else
                                        tagged += ", " + (itm).MainText;
                                }
                                friends.SecondaryText = tagged;
                            };

            var toRight = new XFPanelList();
            SetupFriendSelector(toRight);

            friends.RightPanel = toRight;

            panel.Add(friends);

            var submit = new SenseItem
                               {
                                   MainText = Settings.LocalizationStrings.Checkin
                               };

            submit.Click += (o, e) =>
                            {
                                var check = new FBCheckin
                                                  {
                                                      message = message.Text,
                                                      place = place,
                                                      tags = new FBCheckinTags()
                                                  };

                                foreach (var itm in ((XFPanelList)friends.RightPanel).OfType<SenseItem>())
                                {
                                    check.tags.data.Add((itm).Tag as FBProxyPerson);
                                }

                                wrapper = check.Create();

                                wrapper.GetResults += (wo, we) =>
                                                      {
                                                          if (!FBParseUtilities.HasError(we.Text))
                                                          {
                                                              if (panel.RightPanel != null)
                                                                  panel.RightPanel.Dispose();

                                                              panel.SetRightPanel(null);

                                                              if (panel.InvokeRequired)
                                                                  panel.Invoke(new Action(panel.EnableSlide));
                                                              else
                                                                  panel.EnableSlide();
                                                          }
                                                          else
                                                              MessageBox.Show(Settings.LocalizationStrings.ErrorCheckingIn + ": " + we.Text);
                                                      };
                                wrapper.BeginPost();
                            };

            panel.Add(submit);

            return panel;
        }
    }
}